//
//  LaunchManager.m
//  IMSLink
//
//  Created by Hager Hu on 11/01/2018.
//  Copyright © 2018 Aliyun.com. All rights reserved.
//

#import "LaunchManager.h"

#import <objc/runtime.h>

#import "SDKEntry.h"
#import "IMSSDKEntryProtocol.h"

@interface LaunchManager ()

@property(nonatomic, strong) NSArray *launchList;

@end

@implementation LaunchManager

+ (instancetype)defaultManager {
    static LaunchManager *manager = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
      manager = [[[self class] alloc] init];
    });

    return manager;
}

- (id)init {
    if (self = [super init]) {
        self.launchList = [self loadLaunchClasses];
    }

    return self;
}

- (void)startLaunch {
    for (SDKEntry *entry in self.launchList) {
        if ([NSClassFromString(entry.SDKClassName)
                conformsToProtocol:@protocol(IMSSDKEntryProtocol)]) {
            [NSClassFromString(entry.SDKClassName)
                performSelector:@selector(SDKEntryInit)];
        }
    }
}

#pragma mark -

- (NSArray *)loadLaunchClasses {
    NSMutableArray *entryClasses = [@[] mutableCopy];

    int numClasses;
    Class *classes = NULL;

    classes = NULL;
    numClasses = objc_getClassList(NULL, 0);

    if (numClasses > 0) {
        classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
        numClasses = objc_getClassList(classes, numClasses);
        for (int i = 0; i < numClasses; i++) {
            Class c = classes[i];
            // NSLog(@"%s", class_getName(c));
            NSString *className = [NSString stringWithFormat:@"%s", class_getName(c)];
            if ([className hasPrefix:@"SDKEntry"] &&
                [c conformsToProtocol:@protocol(IMSSDKEntryProtocol)]) {
                SDKEntry *entry = [[SDKEntry alloc] init];
                entry.SDKClassName = className;
                if ([c respondsToSelector:@selector(getSDKDisplayConfig)]) {
                    entry.SDKDisplayConfig =
                        [c performSelector:@selector(getSDKDisplayConfig)];
                    if ([entry.SDKDisplayConfig objectForKey:@"DisplayLevel"]) {
                        entry.displayLevel = [[entry.SDKDisplayConfig objectForKey:@"DisplayLevel"] intValue];
                    } else {
                        entry.displayLevel = 99;  //默认排在后面
                    }
                }

                if ([c respondsToSelector:@selector(getInitLevel)]) {
                    entry.initLevel = [c getInitLevel];
                } else {
                    entry.initLevel = 9.9;  //默认低优先级启动
                }

                [entryClasses addObject:entry];
            }
        }
        free(classes);
    }

    //依据initLevel顺序初始化
    return [entryClasses sortedArrayWithOptions:NSSortStable
                                usingComparator:^NSComparisonResult(SDKEntry *obj1, SDKEntry *obj2) {
                                  float value1 = [obj1 initLevel];
                                  float value2 = [obj2 initLevel];
                                  if (value1 > value2) {
                                      return NSOrderedDescending;
                                  } else if (value1 == value2) {
                                      return NSOrderedSame;
                                  } else {
                                      return NSOrderedAscending;
                                  }
                                }];
}

@end
